package model.time;

import java.util.Calendar;

/**
 * Objects of this class are intended to represent a specific day number monthly repetition  
 * within a dateStart and a dateEnd.
 * @author estoll
 *
 */

public class MonthlyTimeFrame extends TimeFrame {

	
	/**
	 * Constructs a MonthlyTimeFrame object validating possible Exceptions.
	 * @param dateStart GregorianCalendar
	 * @param dateEnd GregorianCalendar
	 * @param t	GregorianCalendar, default date values 1900.01.01, only time values are significant
	 * @param t1 GregorianCalendar, default date values 1900.01.01, only time values are significant
	 * @param dayName String day
	 * @throws NullParametersReceivedExpeption Is thrown if any of the needed parameters are null
	 * @throws InvalidMinutesException Is thrown if the minute field of the time values are not 00 or 30
	 * @throws IllegalTimeValuesException Is thrown if timeEnd <= timeStart
	 */
	public MonthlyTimeFrame(Calendar dateStart, Calendar dateEnd, Calendar t1,
			Calendar t2, String dayName)
			throws NullParametersReceivedExpeption, IllegalTimeValuesException,
			InvalidMinutesException {

		if ((dateStart != null) && (dateEnd != null) && (t1 != null)
				&& (t2 != null) && (dayName != null)) {
			{
				if (((t1.get(Calendar.MINUTE) == 30) || (t1
						.get(Calendar.MINUTE) == 00))
						&& ((t2.get(Calendar.MINUTE) == 30) || (t2
								.get(Calendar.MINUTE) == 00))) {
					if ((t1.equals(t2)) || (t2.before(t1))) {
						throw new IllegalTimeValuesException();
					} else {
						this.setDateStart(dateStart);
						this.setDateEnd(dateEnd);
						this.setTimeStart(t1);
						this.setTimeEnd(t2);
						this.setDayName(dayName);
					}
				} else {
					throw new InvalidMinutesException();
				}
			}
		} else {
			throw new NullParametersReceivedExpeption();
		}
	}

	
	public String getType(){
		return "Monthly";
	}

	public MonthlyTimeFrame() {
		// TODO Auto-generated constructor stub
		super();
	}


	/**
	 * Double Dispatching Calls the method isOverlappedFromMonthlyTimeFrame of
	 * the SingleTimeFrame class, passing this as parameter.
	 * @param withThisObject SingleTimeFrame
	 * @return Boolean
	 */
	public boolean isOverlapped(SingleTimeFrame withThisObject) {
		return (withThisObject.isOverlappedFromMonthlyTimeFrame(this));
	}

	/**
	 * Double Dispatching Calls the method isOverlappedFromMonthlyTimeFrame of
	 * the DailyTimeFrame class, passing this as parameter.
	 * @param withThisObject DailyTimeFrame
	 * @return Boolean
	 */
	public boolean isOverlapped(DailyTimeFrame withThisObject) {
		return (withThisObject.isOverlappedFromMonthlyTimeFrame(this));
	}

	/**
	 * Double Dispatching Calls the method isOverlappedFromMonthlyTimeFrame of
	 * the WeeklyTimeFrame class, passing this as parameter.
	 * @param withThisObject WeeklyTimeFrame
	 * @return Boolean
	 */
	public boolean isOverlapped(WeeklyTimeFrame withThisObject) {
		return (withThisObject.isOverlappedFromMonthlyTimeFrame(this));
	}

	/**
	 * Double Dispatching Calls the method isOverlappedFromMonthlyTimeFrame of
	 * the MonthlyTimeFrame class, passing this as parameter.
	 * @param withThisObject MonthlyTimeFrame
	 * @return Boolean
	 */
	public boolean isOverlapped(MonthlyTimeFrame withThisObject) {
		return (withThisObject.isOverlappedFromMonthlyTimeFrame(this));
	}


	/**
	 * Answers a remote Calls from a Double Dispatch from the MonthlyTimeFrame class.
	 * @param withThisObject MonthlyTimeFrame
	 * @return Boolean
	 */
	public boolean isOverlappedFromMonthlyTimeFrame(MonthlyTimeFrame his) {
		return (((this.getDateStart().get(Calendar.DAY_OF_MONTH) == his
				.getDateStart().get(Calendar.DAY_OF_MONTH)) && (this
				.dateRangeIsOverlapped(his))) && (this.timeIsOverlapped(his)));
	}

	/**
	 * Answers a remote Calls from a Double Dispatch from the DailyTimeFrame class.
	 * @param withThisObject DailyTimeFrame
	 * @return Boolean
	 */
	public boolean isOverlappedFromDailyTimeFrame(DailyTimeFrame his) {
		return ((this.dateRangeIsOverlapped(his)) && (this
				.timeIsOverlapped(his)));
	}

	/**
	 * Answers a remote Calls from a Double Dispatch from the SingleTimeFrame class.
	 * @param withThisObject SingleTimeFrame
	 * @return Boolean
	 */
	public boolean isOverlappedFromSingleTimeFrame(SingleTimeFrame his) {
		return ((his.singleDayIsOverlapped(this)) && (this
				.timeIsOverlapped(his)));
	}

	/**
	 * Answers a remote Calls from a Double Dispatch from the WeeklyTimeFrame class.
	 * @param withThisObject WeeklyTimeFrame
	 * @return Boolean
	 */
	public boolean isOverlappedFromWeeklyTimeFrame(WeeklyTimeFrame his) {
		return ((this.getDayName().equals(his.getDayName()) && (this
				.dateRangeIsOverlapped(his))) && (this.timeIsOverlapped(his)));
	}

}
